#include "gwInterface.h"
#include "db.h"
#include "cJSON.h"
#include "logger.h"
#include "version.h"
#include <string.h>
#include <stdlib.h>

#define GW_INTERFACE_TABLE_NAME "t_gw_interface"
#define SQL_GW_INTERFACE_TABLE_CREATE "CREATE TABLE IF NOT EXISTS " GW_INTERFACE_TABLE_NAME " (id INT PRIMARY KEY NOT NULL, name TEXT NOT NULL, addr TEXT NOT NULL, port INT, isUsed INT, ifType INT NOT NULL, params TEXT)"
#define SQL_GW_INTERFACE_TABLE_INSERT(...) "INSERT INTO " GW_INTERFACE_TABLE_NAME "(id, name, addr, port, isUsed, ifType, params) VALUES (" #__VA_ARGS__ ")"
#define SQL_GW_INTERFACE_TABLE_REPLACE(...) "REPLACE INTO " GW_INTERFACE_TABLE_NAME "(id, name, addr, port, isUsed, ifType, params) VALUES (" #__VA_ARGS__ ")"
#define SQL_GW_INTERFACE_TABLE_DELETE(id) "DELETE FROM " GW_INTERFACE_TABLE_NAME " WHERE id = " #id
#define SQL_GW_INTERFACE_TABLE_SELECT(id) "SELECT * FROM " GW_INTERFACE_TABLE_NAME " WHERE id = " #id



/*===============================================================*/
/* 模型 */
char* getSerialParamsStr(T_GW_INTERFACE* interface){
    if(NULL == interface){
        log_file_e(APPNAME, "getSerialParamsStr: product is NULL");
        return NULL;
    }

    cJSON* root = cJSON_CreateObject();
    if(NULL == root){
        log_file_e(APPNAME, "getSerialParamsStr: cJSON_CreateObject failed");
        return NULL;
    }
   cJSON_AddItemToObject(root, "baudRate", cJSON_CreateNumber(interface->params.baudRate));
   cJSON_AddItemToObject(root, "dataBits", cJSON_CreateNumber(interface->params.dataBits));
   cJSON_AddItemToObject(root, "parity", cJSON_CreateString(interface->params.parity));
   cJSON_AddItemToObject(root, "stopBits", cJSON_CreateNumber(interface->params.stopBits));
    char* str = cJSON_Print(root);
    cJSON_Delete(root);
    return str;
}

void getSerialParams(const char* paramsStr, T_GW_INTERFACE* interface){
    if((NULL == paramsStr) || (NULL == interface)){
        log_file_e(APPNAME, "getSerialParams: paramsStr or interface is NULL");
        return;
    }
    cJSON* root = cJSON_Parse(paramsStr);
    if(NULL == root){
        log_file_e(APPNAME, "getSerialParams: cJSON_Parse failed");
        return;
    }
    int i = 0;
    if(cJSON_IsObject(root)){
        cJSON* item = NULL;
        item = cJSON_GetObjectItem(root, "baudRate");
        if(cJSON_IsNumber(item)){
            interface->params.baudRate = item->valueint;
        }
        item = cJSON_GetObjectItem(root, "dataBits");
        if(cJSON_IsNumber(item)){
            interface->params.dataBits = item->valueint;
        }
        item = cJSON_GetObjectItem(root, "parity");
        if(cJSON_IsString(item)){
            strcpy(interface->params.parity, item->valuestring);
        }
        item = cJSON_GetObjectItem(root, "stopBits");
        if(cJSON_IsNumber(item)){
            interface->params.stopBits = item->valueint;
        }
    }
}

char* getParamsStr(T_GW_INTERFACE* interface){
    if(NULL == interface){
        log_file_e(APPNAME, "getParamsStr: interface is NULL");
        return NULL;
    }

    switch (interface->ifType)
    {
    case GW_INTERFACE_UART:
        /* code */
        return getSerialParamsStr(interface);
        break;
    case GW_INTERFACE_NET:
        break;
    default:
        break;
    }
    return NULL;
}

char* getParams(const char* paramsStr, T_GW_INTERFACE* interface){
    if(NULL == interface){
        log_file_e(APPNAME, "getParams: interface is NULL");
        return NULL;
    }

    switch (interface->ifType)
    {
    case GW_INTERFACE_UART:
        /* code */
        getSerialParams(paramsStr, interface);
        break;
    case GW_INTERFACE_NET:
        break;
    default:
        break;
    }
    return NULL;
}

int createGWInterfaceTable(){
    return db_create_table(SQL_GW_INTERFACE_TABLE_CREATE);
}

int insertGWInterface(T_GW_INTERFACE* interface){
    if(NULL == interface){
        log_file_e(APPNAME, "insert gateway interface is NULL");
        return -1;
    }
    char* params = getParamsStr(interface);
    int ret = db_insert(SQL_GW_INTERFACE_TABLE_INSERT(interface->id, interface->name, interface->addr, interface->port, interface->isUsed, interface->ifType, interface->params));
    cJSON_free(params);
    return ret;
}

int replaceGWInterface(T_GW_INTERFACE* interface){
    if(NULL == interface){
        log_file_e(APPNAME, "replace gateway interface is NULL");
        return -1;
    }
    char* params = getParamsStr(interface);
    int ret = db_insert(SQL_GW_INTERFACE_TABLE_REPLACE(interface->id, interface->name, interface->addr, interface->port, interface->isUsed, interface->ifType, interface->params));
    cJSON_free(params);
    return ret;
}

int deleteGWInterface(T_GW_INTERFACE* interface){
    if(NULL == interface){
        log_file_e(APPNAME, "delete gateway interface is NULL");
        return -1;
    }
    return db_delete(SQL_GW_INTERFACE_TABLE_DELETE(interface->id));
}

static int GWInterfaceCallback(void *data, int argc, char **argv, char **azColName){
    int i = 0;
    if(NULL == data){
        log_file_e(APPNAME, "GWInterfaceCallback data is NULL");
        return -1;
    }
    T_GW_INTERFACE_LIST* ifList = (T_GW_INTERFACE_LIST*)data;
    if((0 == ifList->count) || (NULL == ifList->head)){
        ifList->head = ifList->tail = (T_GW_INTERFACE*)malloc(sizeof(T_GW_INTERFACE));
        ifList->head->next = NULL;
        ifList->head->prev = NULL;
    } else {
        ifList->tail->next = (T_GW_INTERFACE*)malloc(sizeof(T_GW_INTERFACE));
        ifList->tail->next->prev = ifList->tail;
    }
    ifList->count++;
    for(i = 0; i < argc; i++){
        if(0 == strcmp(azColName[i], "id")){
            ifList->tail->id = atoll(argv[i]);
        } else if(0 == strcmp(azColName[i], "name")){
            if(NULL == argv[i]){
                ifList->tail->name[0] = '\0';
            } else {
                strcpy(ifList->tail->name, argv[i]);
            }
        } else if(0 == strcmp(azColName[i], "addr")){
            if(NULL == argv[i]){
                ifList->tail->addr[0] = '\0';
            } else {
                strcpy(ifList->tail->addr, argv[i]);
            }
        } else if(0 == strcmp(azColName[i], "port")){
            ifList->tail->port = atoi(argv[i]);
        } else if(0 == strcmp(azColName[i], "isUsed")){
            ifList->tail->isUsed = atoi(argv[i]);
        } else if(0 == strcmp(azColName[i], "ifType")){
            ifList->tail->ifType = atoi(argv[i]);
        } else if(0 == strcmp(azColName[i], "params")){
            if(NULL != argv[i]){
                getParams(argv[i], ifList->tail);
            }
        }
        log_i("%s = %s", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    return ifList->count;
}

int selectGWInterface(const char* sql, T_GW_INTERFACE_LIST* ifList){
    if((NULL == sql) || (1 > strlen(sql)) || (NULL == ifList)){
        log_file_e(APPNAME, "select gateway interface sql is NULL");
        return -1;
    }
    return db_select(sql, GWInterfaceCallback, ifList);

}
//
void dbGWInterfaceInit(){
    createGWInterfaceTable();
}
